module ecs {
    export class Core extends eui.UILayer {
        public static Emitter: Emitter;
        public static entitySystemsEnabled: boolean;
        public static _instance: Core;

        private _globalManagers: FastList<GlobalManager> = new FastList<GlobalManager>();
        private _scene: Scene;
        private _nextScene: Scene;
        public _sceneTransition: SceneTransiton;

        public static Scene(scene?: Scene): Scene {
            if (scene == null) {
                return Core._instance._scene;
            } else {
                if (!Core._instance._scene) {
                    Core._instance._scene = scene;
                    Core._instance._scene.Begin();
                    Core._instance.OnSceneChanged();
                }
            }
        }

        constructor(enableEntitySystems: boolean = true) {
            super();

            Core._instance = this;
            Core.Emitter = new Emitter();
            Core.entitySystemsEnabled = enableEntitySystems;

            this.addEventListener(egret.Event.ENTER_FRAME, this.Update, this);
        }

        protected Update(e: egret.Event) {
            Time.Update();

            if (this._scene) {
                for (let i = this._globalManagers.Length - 1; i >= 0; i--) {
                    if (this._globalManagers.Buffer[i].Enabled)
                        this._globalManagers.Buffer[i].Update();
                }

                if (!this._sceneTransition ||
                    (this._sceneTransition &&
                        (!this._sceneTransition._loadsNewScene || this._sceneTransition._isNewSceneLoaded))) {
                    this._scene.Update();
                }

                if (this._nextScene){
                    this._scene.End();

                    this._scene = this._nextScene;
                    this._nextScene = null;
                    this.OnSceneChanged();

                    this._scene.Begin();
                }
            }
        }

        /** 在场景结束之后，下一个场景开始之前调用 */
        private OnSceneChanged() {
            Core.Emitter.Emit("SceneChanged");

            /** js gc 如果都不起作用 只能等待自动gc */
            if (typeof window["CollectGarbage"] === "function") {
                window["CollectGarbage"]();
            } else if (window["opera"] && window["opera"]["collect"]) {
                window["opera"]["collect"]();
            }
        }

        /**
         * 添加一个全局管理器对象，在调用Scene.update之前，将在每个帧中使用其更新方法
         * @param manager 
         */
        public static RegisterGlobalManager(manager: GlobalManager) {
            Core._instance._globalManagers.Add(manager);
            manager.Enabled = true;
        }

        /**
         * 删除全局管理器对象
         * @param manager 
         */
        public static UnregisterGlobalManager(manager: GlobalManager) {
            Core._instance._globalManagers.Remove(manager);
            manager.Enabled = false;
        }

        /**
         * 获取全局管理器对象
         */
        public static GetGlobalManager<T extends GlobalManager>(): T {
            for (let i = 0; i < Core._instance._globalManagers.Length; i++) {
                if (Core._instance._globalManagers.Buffer[i] instanceof GlobalManager) {
                    return <T>Core._instance._globalManagers.Buffer[i];
                }
            }

            return null;
        }
    }
}